package com.feonix.common.basedao;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;

import com.feonix.common.exception.SqlInjectionException;
import com.feonix.common.util.SqlUtil;

public class UpdateSql {

	/**
	 * update的表
	 */
	private String tableName;

	private Map<String, Object> params = new HashMap<String, Object>();

	private Map<String, Object> whereParams = new HashMap<String, Object>();

	/**
	 * where语句
	 */
	private String where;

	/**
	 * 构造一个updatesql
	 * 
	 * @param tableName
	 */
	public UpdateSql(String tableName) {
		this.tableName = tableName;
	}

	/**
	 * 构造一个updatesql
	 * 
	 * @param tableName
	 * @param where
	 */
	public UpdateSql(String tableName, String where) {
		this.tableName = tableName;
		this.where = where;
	}

	/**
	 * 
	 * @param key
	 * @param value
	 */
	public void addParam(String key, Object value) {
		this.params.put(key, value);
	}

	/**
	 * 原生语句
	 * 
	 * @param key
	 * @param value
	 */
	public void addParamNative(String key, String value) {
		this.params.put("nav:" + key, value);
	}

	/**
	 * 更新的String字段
	 * 
	 * @param key
	 * @param value
	 */
	public void addString(String key, String value) {
		this.params.put(key, value);
	}

	/**
	 * 更新的date字段
	 * 
	 * @param key
	 * @param value
	 */
	public void addDate(String key, Date value) {
		this.params.put(key, value);
	}

	/**
	 * 更新的int字段，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addInt(String key, Integer value) {
		this.params.put(key, value);
	}

	/**
	 * 更新的int字段，1:true , 0:false
	 * 
	 * @param key
	 * @param value
	 */
	public void addInt(String key, Boolean value) {
		this.params.put(key, Integer.valueOf(BooleanUtils.toInteger(value.booleanValue())));
	}

	/**
	 * 更新的double字段，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addDouble(String key, Double value) {
		this.params.put(key, value);
	}

	/**
	 * 更新的long字段，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addLong(String key, Long value) {
		this.params.put(key, value);
	}

	/**
	 * 更新的float字段，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addFloat(String key, Float value) {
		this.params.put(key, value);
	}

	/**
	 * 更新的float字段，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParam(String key, Object value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置string型的where条件
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamString(String key, String value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置string型的where条件，为 LIKE 参数填充值
	 * 
	 * @param key
	 * @param value
	 * @param likeType
	 */
	public void addWhereParamString(String key, String value, LikeType likeType) {
		this.whereParams.put(key, SqlUtil.getLikeValue(value, likeType));
	}

	/**
	 * 设置int型的where条件，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamInt(String key, Integer value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置int型的where条件，1:true , 0:false
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamInt(String key, Boolean value) {
		this.whereParams.put(key, Integer.valueOf(BooleanUtils.toInteger(value.booleanValue())));
	}

	/**
	 * 设置double型的where条件，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamDouble(String key, Double value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置long型的where条件，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamLong(String key, Long value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置float型的where条件，是包装类可以为null
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamFloat(String key, Float value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置date型的where条件
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamDate(String key, Date value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置集合类型条件，如 IN (:xxxx)
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamList(String key, Collection<?> value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 设置数组类型条件，如 IN (:xxxx)
	 * 
	 * @param key
	 * @param value
	 */
	public void addWhereParamArray(String key, Object[] value) {
		this.whereParams.put(key, value);
	}

	/**
	 * 
	 * @return
	 * @throws Exception
	 */
	protected String getSql() throws Exception {
		StringBuffer sqlBuffer = new StringBuffer();
		sqlBuffer.append("UPDATE ").append(this.tableName).append(" SET ");
		Set<Entry<String, Object>> params = this.params.entrySet();
		StringBuffer valueSql = new StringBuffer();
		for (Iterator<Entry<String, Object>> iterator = params.iterator(); iterator.hasNext();) {
			Entry<String, Object> entry = iterator.next();
			if (entry.getKey().startsWith("nav:")) {
				valueSql.append(StringUtils.replaceOnce(entry.getKey(), "nav:", "")).append("=")
						.append(entry.getValue()).append(",");
			} else {
				valueSql.append(entry.getKey()).append("=:").append(entry.getKey()).append(",");
			}
		}
		valueSql.deleteCharAt(valueSql.length() - 1);
		String value = valueSql.toString();
		valueSql.delete(0, valueSql.length());
		sqlBuffer.append(value);
		if (!(StringUtils.isBlank(this.where))) {
			if (!(SqlUtil.isSafeSql(this.where))) {
				throw new SqlInjectionException("sql.injection", new Object[] { this.where });
			}
			sqlBuffer.append(" WHERE ").append(this.where);
			int i = this.params.size() + this.whereParams.size();
			this.params.putAll(this.whereParams);
			if (this.params.size() != i) {
				throw new Exception("UpdateSql params and whereParams key repeat");
			}
		}
		String sql = sqlBuffer.toString();
		sqlBuffer.delete(0, sqlBuffer.length());
		return sql;
	}

	protected Map<String, Object> getParams() {
		return this.params;
	}

	/**
	 * 设置where语句
	 * 
	 * @param where
	 */
	public void setWhere(String where) {
		this.where = where;
	}

}
